
package inteligenciaartificial;

import java.util.Arrays;
import java.util.Collections;


public class Generacion {
    
    //El nro de generación, usado para identificar una generación 
    //y para calcular probabilidad de mutación cuando se usa temperatura ascendente o descendente
    private int nroDeGeneracion;
    //Individuos que conforman una generación puntual
    private Individuo[] individuos;
    
    public Generacion(Individuo[] seleccionados, Individuo[] cruzados,Individuo[] mutados, int nroDeGeneracion){
        this.nroDeGeneracion= nroDeGeneracion;
        individuos= new Individuo[Settings.totalPoblacion];
        for(int i =0;i<seleccionados.length;i++){
            Individuo ind= seleccionados[i];
            ind.setNroIndividuo(i);
            ind.setNroGeneracion(this.nroDeGeneracion);
            individuos[i]= ind;
        }
        for(int i =0; i<cruzados.length; i++){
            Individuo ind= cruzados[i];
            ind.setNroIndividuo(i+seleccionados.length);
            ind.setNroGeneracion(this.nroDeGeneracion);
            individuos[i+seleccionados.length] = ind;
        }
        for(int i =0; i<mutados.length; i++){
            Individuo ind= mutados[i];
            ind.setNroIndividuo(i+cruzados.length+seleccionados.length);
            ind.setNroGeneracion(this.nroDeGeneracion);
            individuos[i+cruzados.length+seleccionados.length] = ind;
        }
        
    }
    
    public Generacion(Individuo[] semilla){
        this.individuos = semilla;
        this.nroDeGeneracion= 0;
    }
    
    public Individuo[] getIndividuos(){
        return this.individuos;
    }
    
    public Individuo getIndividuoNumero(int index){
        return individuos[index];
    }

    /**
     * @return the nroDeGeneracion
     */
    public int getNroDeGeneracion() {
        return nroDeGeneracion;
    }

    /**
     * @param nroDeGeneracion the nroDeGeneracion to set
     */
    public void setNroDeGeneracion(int nroDeGeneracion) {
        this.nroDeGeneracion = nroDeGeneracion;
    }
    
    public int obtenerMejorAptitud (){
        Individuo[] individuosOrdenados= individuos.clone();
        Arrays.sort(individuosOrdenados, Collections.reverseOrder());
        return AptitudUtilidad.calcularAptitud(individuosOrdenados[0]);    
    }

    public int obtenerPeorAptitud (){
        Individuo[] individuosOrdenados= individuos.clone();
        Arrays.sort(individuosOrdenados);
        return AptitudUtilidad.calcularAptitud(individuosOrdenados[0]);
    }
    
    public int calcularAptitudPromedio(){
        int total = 0;
        for (int i=0; i<individuos.length; i++) {
            total=total+AptitudUtilidad.calcularAptitud(individuos[i]);
        }
        return (int)(total/(double)individuos.length);
    }
    
    public Individuo obtenerMejorIndividuo (){
        Individuo[] individuosOrdenados= individuos.clone();
        Arrays.sort(individuosOrdenados, Collections.reverseOrder());
        return individuosOrdenados[0];    
    }
    
   public Individuo obtenerPeorIndividuo (){
        Individuo[] individuosOrdenados= individuos.clone();
        Arrays.sort(individuosOrdenados);
        return individuosOrdenados[0];
    }
    
    public Individuo[] obtenerMejoresIndividuos(int cantidad){
        
        Individuo[] mejoresIndividuos= new Individuo[cantidad];
        
        Individuo[] individuos= this.individuos.clone();
        
        Arrays.sort(individuos, Collections.reverseOrder());
        
        mejoresIndividuos[0]= individuos[0];
 
        //recorro todas las posiciones de mejores individuos
        for(int i=1;i<mejoresIndividuos.length;i++){
            //for(int j=0;j<individuos.length;j++){
            int j=0;

            
            //para recorrer todos los individuos de la poblacion
            while(j<individuos.length){ 
                 boolean yaExiste=false;
                //recorrro desde donde estoy en mejores individuos hacia atras
                //si encuentro alguno igual pongo yaExiste a verdadero
                for(int k=1;k<=i;k++){
                   if(mejoresIndividuos[i-k].individuosIguales(individuos[j])){
                       yaExiste=true;
                   }
                }
                
                //si no existe lo copio y salgo del while
                if(!yaExiste){
                    //entra si son distintos
                    mejoresIndividuos[i]=individuos[j];
                    j=individuos.length; //para salir
                    
                }else{
                    //si ya existe avanzo
                    j++;
                }
            }
            
            //TODO:
            //check si encontro un individuo, por ahora suponemos que si
        }
        
        return mejoresIndividuos;
        
    }
    
}
